/**
 * Copyright (c) 2025 myons Inc. All rights reserved.
 */
package cn.zmwh.im.server.netty;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.collection.CollUtil;
import cn.zmwh.im.common.pojo.dto.IMRecvInfo;
import cn.zmwh.im.common.pojo.dto.IMUserInfo;
import cn.zmwh.im.common.pojo.dto.transfer.MessagePrivate;
import cn.zmwh.im.server.config.HintManager;
import cn.zmwh.im.server.constant.BsKImConstant;
import cn.zmwh.im.server.constant.IMCmdConstants;
import cn.zmwh.im.server.modules.message.pojo.entity.ImMessage;
import cn.zmwh.im.server.modules.message.service.ImMessageService;
import cn.zmwh.im.server.modules.ums.pojo.dto.MessageDB;
import cn.zmwh.im.server.modules.ums.service.ImUserService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;

import java.util.*;
import java.util.stream.Collectors;

/**
 * @describe: 消息发送 、
 * @author: dmzmwh 、
 * @time: 2025-06-25 16:54 、
 */
@Slf4j
@Service
public class MessageService {


    @Autowired
    private ImUserService imUserService;
    @Autowired
    private ImMessageService imMessageService;
    @Autowired
    private RedisTemplate redisTemplate;

    /**
     * 消息处理
     *
     * @param imMessage
     * @param recvId
     * @param sendInfo
     * @param isSaveSend 是否保存发送方
     */
    public void messageSendPrivate(ImMessage imMessage, String messageQueue, Long recvId, IMUserInfo sendInfo, boolean isSaveSend) {
        String messageId = imMessage.getMessageId();
        Set<Long> ids = Set.of(recvId);
        List<IMUserInfo> userInfos = imUserService.uidToOnline(ids);
        Map<String, List<IMUserInfo>> mapByServerId = new HashMap<>();
        if (CollUtil.isNotEmpty(userInfos)) {
            userInfos.forEach(dto -> {
                String serverId = dto.getServerId();
                mapByServerId.computeIfAbsent(serverId, k -> new ArrayList<>()).add(dto);  // 转型并存入父类 List
            });
        }

        List<ImMessage> imList = new ArrayList<>();
        ImMessage recvImMessage = new ImMessage();
        BeanUtil.copyProperties(imMessage, recvImMessage);
        recvImMessage.setUid(recvId);
        if (CollUtil.isNotEmpty(mapByServerId)) {//好友存在在线终端
            MessagePrivate messagePrivate = new MessagePrivate();
            BeanUtil.copyProperties(imMessage, messagePrivate);
            IMRecvInfo imRecvInfo = new IMRecvInfo();
            imRecvInfo.setCmd(IMCmdConstants.PRIVATE_MESSAGE);
            imRecvInfo.setData(messagePrivate);
            imRecvInfo.setMessageId(messageId);
            imRecvInfo.setSender(sendInfo);
            Set<Map.Entry<String, List<IMUserInfo>>> entries = mapByServerId.entrySet();
            for (Map.Entry<String, List<IMUserInfo>> entry : entries) {
                String key = entry.getKey();
                List<IMUserInfo> value = entry.getValue();
                imRecvInfo.setReceivers(value);
                String queueKey = String.join(":", messageQueue, key);
                redisTemplate.opsForList().rightPush(queueKey, imRecvInfo);
            }
            recvImMessage.setStatus(1);//接收消息是待推送
            imMessage.setStatus(1);//发送消息是已投递
        } else {
            recvImMessage.setStatus(5);//不存在在现在终端，直接等待重连时候推送离线消息
        }
        if (isSaveSend) {
            imList.add(imMessage);
        }
        imList.add(recvImMessage);

        //保存消息
        try (HintManager hintManager = HintManager.getInstance()) {
            Set<Long> userIds = imList.stream().map(ImMessage::getUid).collect(Collectors.toSet());
            Set<MessageDB> messageDBS = imUserService.qryMessageDb(userIds);
            for (MessageDB messageDB : messageDBS) {
                Integer messageDb = messageDB.getDb();
                Integer messageTable = messageDB.getTable();
                Set<Long> itemUserIds = messageDB.getUserIds();
                List<ImMessage> itemList = imList.stream().filter(item -> itemUserIds.contains(item.getUid())).collect(Collectors.toList());
                hintManager.addDbValue(BsKImConstant.DbName.IM_MESSAGE, messageDb);
                hintManager.addTableValue(messageTable);
                imMessageService.saveBatch(itemList);
            }
        }
    }
}
